﻿using System;
using System.Collections.Generic;
using System.IO;
using Windows.UI.Xaml.Media.Imaging;
using System.Linq;
using System.Windows.Input;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Input;
using Windows.UI.Core;
using System.Threading;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;

namespace RoboRun
{
    class PrepareToPlay
    {

        public static bool userHasHitObstacleOrWall = false;
        public static async void prepareToPlay(Image Countdown, float height, float width, float offset,TextBlock CommandQueueTextBox)
        {
            await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(1000));
            CountdownAnimation.countdownAnimation(Countdown, height, width, offset);
            await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(5000));
            startMovingRobot(CommandQueueTextBox);
        }

        private static int index = 0;

        //variables used for if statement
        private static bool ifListener = false;
        static int firstEntryForElse = 0;
        static int lastEntryForElse = 0;

        //variables used for for loop
        private static bool forListener = false;

        private static int numberOfIterations;
        private static int startEntryOfForLoop;
        private static int endEntryOfForLoop;
        private static int counterforForLoop;

        //variables used for while loop

        private static bool whileListener = false;
        private static int startEntryOfWhileLoop;
        private static int endEntryOfWhileLoop;

        private static String temporaryCommand = "";
        private static bool forceEndLoop = false;
        private static String lastCommandInForLoop = "";
        private static String lastCommandInWhileLoop = "";

        


        private async static void startMovingRobot(TextBlock CommandQueueTextBox) //first distinguish what are we doing? straight, turn, loop?
        { //make it a while loop: "while the marker which dictates whether the user has hit an obstacle = false"
            //when the marker becomes true, cease reading from the commandQueue

            if (userHasHitObstacleOrWall == false)
            {
                for (int i = index; i < GameplayScreen.commandQueue.Count; i++)
                {
                    
                    if (ifListener == true)
                    {
                        if (GameplayScreen.commandQueue[i].Contains("Else"))
                        {
                            for (int k = i+1; k < GameplayScreen.commandQueue.Count; k++)
                            {
                                if (GameplayScreen.commandQueue[k].Contains("\t")) //contains tab implies it is in the else clause
                                {
                                    int count = GameplayScreen.commandQueue.Count;
                                    if (k == count - 1)
                                    {
                                        forceEndLoop = true;
                                        break;
                                    }
                                }
                               
                                else
                                {
                                    i = k;
                                    break;
                                }
                            }
                            ifListener = false;
                            //again, delay should depend on what was being called before, if go straight 2 was called before, then change delay accordingly.
                            await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(3500));
                            //maybe add a prompt saying calculating or "please wait". 
                        }
                    }

                    if (forceEndLoop == true)
                    {
                        forceEndLoop = false;
                        break;
                    }
                    if (forListener == true)
                    {
                        if (i == startEntryOfForLoop + 1)
                        {

                            if ((GameplayScreen.commandQueue[i].Contains("Rotate Anti-Clockwise") && temporaryCommand.Contains("Rotate Clockwise")))
                            {
                                tg.Children.RemoveAt(tg.Children.Count - 1);
                                GameplayScreen.RobotSpriteRef.RenderTransform = tg;
                                updateDirectionLeft(GameplayScreen.RobotCurrentDirection);
                                i++;
                                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(500));
                                temporaryCommand = ""; //may not be necessary...
                            }
                            else if ((GameplayScreen.commandQueue[i].Contains("Rotate Clockwise") && temporaryCommand.Contains("Rotate Anti-Clockwise")))
                            {
                                tg.Children.RemoveAt(tg.Children.Count - 1);
                                GameplayScreen.RobotSpriteRef.RenderTransform = tg;
                                updateDirectionRight(GameplayScreen.RobotCurrentDirection);
                                i++;
                                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(500));
                                temporaryCommand = "";
                            }
                        }
                       
                        if (GameplayScreen.commandQueue[i].Equals("]"))
                        {
                            if (counterforForLoop >= numberOfIterations - 1)
                            {
                                counterforForLoop = 0;
                                forListener = false;
                                GameplayScreen.debugger.Text = "Done with For Loop";
                            }
                            else
                            {
                                temporaryCommand = GameplayScreen.commandQueue[i-1];
                                i = startEntryOfForLoop;
                                counterforForLoop++;
                            }
                            //delays should depend on what is being called.
                            useAppropriateDelayFor();
                    
                        }
                    }

                    if (whileListener == true)
                    {
                        if (GameplayScreen.commandQueue[i].Equals("]"))
                        {
                                i = startEntryOfWhileLoop;
                                useAppropriateDelayWhile();
                        }
                        

                    }

                    
                    //UPDATE: fix implemented, make sure it is okay. ^_^
                    if (userHasHitObstacleOrWall == true)
                    {
                        break;
                    }
                    //
                    if (i >= 1)
                    {
                        if (GameplayScreen.commandQueue[i - 1].Contains("Go Straight 2 squares") && GameplayScreen.commandQueue[i].Contains("Rotate"))
                        {
                            await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(7000));
                        } //to prevent the game reading the arraylist too quickly.
                        if (GameplayScreen.commandQueue[i - 1].Contains("Go Straight 1") && GameplayScreen.commandQueue[i].Contains("Go Straight 1"))
                        {
                            await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(700));
                        }
                        else
                        {
                            for (int j = 1; j <= 9; j++) //adds a delay depending on how many squares straight the user is moving in the previous command.
                            {
                                if (GameplayScreen.commandQueue[i - 1].Contains("Go Straight") && GameplayScreen.commandQueue[i].Contains("Go Straight" + " " + j))
                                {
                                    await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(1800 * j));
                                    break;
                                }
                            }
                        }
                    }
            
                    await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(1000));

                    if (GameplayScreen.commandQueue[i].Contains("If")) //if statement
                    {
                        //if statement detection
                        int indexOfNumberOfIterations = GameplayScreen.commandQueue[i].IndexOf("squares") - 2;
                        Char[] chararray = GameplayScreen.commandQueue[i].ToCharArray();
                        int value = Int32.Parse(chararray[indexOfNumberOfIterations].ToString());
                        IfElse.userEntry = value;
                        //find out what comparative operator was used

                        int startIndex = GameplayScreen.commandQueue[i].IndexOf("is");
                        startIndex += 3;
                        int endIndex = indexOfNumberOfIterations;
                        String comparativeOperator = GameplayScreen.commandQueue[i].Substring(startIndex, endIndex - startIndex - 1);
                        IfElse.comparativeOperator = comparativeOperator;
                        GameplayScreen.debugger.Text = comparativeOperator;

                        //i know where the entries for the if clause start, need to know when the else clause starts and ends
                        for (int j = i; j < GameplayScreen.commandQueue.Count; j++)
                        {
                            if (GameplayScreen.commandQueue[j].Contains("Else"))
                            {
                                firstEntryForElse = j;
                                break;
                            }
                        }
                        int lastEntryForIf = firstEntryForElse - 2;
                        for (int k = firstEntryForElse; k < GameplayScreen.commandQueue.Count; k++) //this could be causing errors... just changed from /t to \t
                        {
                            if (GameplayScreen.commandQueue[k].Contains("\t")) //contains tab implies it is in the else clause
                            {

                            }
                            else
                            {
                                lastEntryForElse = k - 1;
                                break;
                            }
                        }

                        if (IfElse.ifElse() == true)
                        {
                            ifListener = true;
                        }
                        else
                        {
                            i = lastEntryForElse; //skip all the entries in the if clause and just go for the else clause
                        }
                    }
                    else if (GameplayScreen.commandQueue[i].Contains("For"))
                    {
                        //for loop detection
                        //firstly, let's find how many iterations the user wanted
                        Char[] charArray = GameplayScreen.commandQueue[i].ToCharArray();
                        
                        Char number = charArray[7];
                        numberOfIterations = Int32.Parse(number.ToString());
                        startEntryOfForLoop = i + 1;
                        
                        for (int j = startEntryOfForLoop; j < GameplayScreen.commandQueue.Count; j++)
                        {
                            if (GameplayScreen.commandQueue[j].Equals("]"))
                            {
                                endEntryOfForLoop = j;
                                 lastCommandInForLoop = GameplayScreen.commandQueue[j - 1];
                            }
                        }
                        forListener = true;
                        //so if entry = endEntryOfForLoop then go back to startEntryOfForLoop, keeping track with a counter
                    }

                    else if (GameplayScreen.commandQueue[i].Contains("While"))
                    {
                        //while loop detection
                        //firstly, let's find out where the end of the loop is
                        for (int j = i+1; j < GameplayScreen.commandQueue.Count; j++)
                        {
                            if (GameplayScreen.commandQueue[j].Equals("]"))
                            {
                                endEntryOfWhileLoop = j;

                                lastCommandInWhileLoop = GameplayScreen.commandQueue[j - 1];
                            }
 
                        }
                        whileListener = true;
                        //now check if condition is true, temporarily using ifelse class. if it doesn't work, make new class especially for while loop using same logic

                        //extracting user value
                        int indexOfNumberOfIterations = GameplayScreen.commandQueue[i].IndexOf("squares") - 2; //correct
                        Char[] chararray = GameplayScreen.commandQueue[i].ToCharArray();
                        int value = Int32.Parse(chararray[indexOfNumberOfIterations].ToString());
                        IfElse.userEntry = value; //should be fine

                        //extracting condition
                        int startIndex = GameplayScreen.commandQueue[i].IndexOf("is");
                        startIndex += 3;
                        int endIndex = indexOfNumberOfIterations;
                        String comparativeOperator = GameplayScreen.commandQueue[i].Substring(startIndex, endIndex - startIndex - 1);
                        IfElse.comparativeOperator = comparativeOperator;
                        GameplayScreen.debugger.Text = comparativeOperator; //should be fine, bit risky, check

                        if (IfElse.ifElse() == false)
                        {
                            i = endEntryOfWhileLoop;
                        }

                    }
                    //There's a glitch where if you do turn left and then turn right (or vice versa), it does not animate correctly, the two if statements below aim to deal with this.
                    else if (i >= 1 && GameplayScreen.commandQueue[i].Contains("Rotate Clockwise") && GameplayScreen.commandQueue[i - 1].Contains("Rotate Anti-Clockwise") || (GameplayScreen.commandQueue[i].Equals("\tRotate Clockwise") && GameplayScreen.commandQueue[i - 1].Equals("\tRotate Anti-Clockwise")) || (GameplayScreen.commandQueue[i].Equals("   Rotate Clockwise") && GameplayScreen.commandQueue[i - 1].Equals("   Rotate Anti-Clockwise")))
                    {
                        tg.Children.RemoveAt(tg.Children.Count - 1);
                        GameplayScreen.RobotSpriteRef.RenderTransform = tg;
                        updateDirectionRight(GameplayScreen.RobotCurrentDirection);
                        await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(500));
                    }

                    else if (i >= 1 && (GameplayScreen.commandQueue[i].Equals("Rotate Anti-Clockwise") && GameplayScreen.commandQueue[i - 1].Equals("Rotate Clockwise")) || (GameplayScreen.commandQueue[i].Equals("\tRotate Anti-Clockwise") && GameplayScreen.commandQueue[i - 1].Equals("\tRotate Clockwise")) || (GameplayScreen.commandQueue[i].Equals("   Rotate Anti-Clockwise") && GameplayScreen.commandQueue[i - 1].Equals("   Rotate Clockwise")))
                    {
                        tg.Children.RemoveAt(tg.Children.Count - 1);
                        GameplayScreen.RobotSpriteRef.RenderTransform = tg;
                        updateDirectionLeft(GameplayScreen.RobotCurrentDirection);
                        await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(500));
                    }

                    // reads command queue and does appropriate methods
                    else if (GameplayScreen.commandQueue[i].Contains("Go Straight"))
                    {
                        moveRobotStraight(GameplayScreen.commandQueue[i]);
                        await setStraightDelay(i);
                    }
                    else if (GameplayScreen.commandQueue[i].Contains("Rotate Anti-Clockwise"))
                    {
                        turnRobotLeft();
                        updateDirectionLeft(GameplayScreen.RobotCurrentDirection);
                        await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(500));
                    }
                    else if (GameplayScreen.commandQueue[i].Contains("Rotate Clockwise"))
                    {
                        turnRobotRight();
                        updateDirectionRight(GameplayScreen.RobotCurrentDirection);
                        await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(500));
                    }
                }

                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(4000));
                if (GameplayScreen.RobotCurrentPosition.Equals(GameplayScreen.GoalPosition))
                {

                }
                else
                {
                    GameplayScreen.commandExecuted = "Game Over End Of Queue";
                    GameplayScreen.gameOverEndOfQueue();
                }

               
            }
        }

        private static async System.Threading.Tasks.Task setStraightDelay(int i)
        {
            if (GameplayScreen.commandQueue[i].Contains("Go Straight 4"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(16000));
            }
            else if (GameplayScreen.commandQueue[i].Contains("Go Straight 3"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(12500));
            }
            else if (GameplayScreen.commandQueue[i].Contains("Go Straight 2"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(3000));
            }
            else if (GameplayScreen.commandQueue[i].Contains("Go Straight 1"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(3500));
            }
            
        }

        private static void updateDirectionLeft(String direction)
        {
            switch (direction)
            {
                case "North" :
                    GameplayScreen.RobotCurrentDirection = "West";
                    break;
                case "West":
                    GameplayScreen.RobotCurrentDirection = "South";
                    break;
                case "South" :
                    GameplayScreen.RobotCurrentDirection = "East";
                    break;
                case  "East":
                    GameplayScreen.RobotCurrentDirection = "North";
                    break;
            }
            GameplayScreen.debugger.Text = GameplayScreen.RobotCurrentDirection;
        }

        private static void updateDirectionRight(String direction)
        {
            switch (direction)
            {
                case "North":
                    GameplayScreen.RobotCurrentDirection = "East";
                    break;
                case "West":
                    GameplayScreen.RobotCurrentDirection = "North";
                    break;
                case "South":
                    GameplayScreen.RobotCurrentDirection = "West";
                    break;
                case "East":
                    GameplayScreen.RobotCurrentDirection = "South";
                    break;
            }
            GameplayScreen.debugger.Text = GameplayScreen.RobotCurrentDirection;
        }

        private static bool turnOccured;

        private static RotateTransform rt = new RotateTransform();
        private static TransformGroup tg = new TransformGroup();

        private static void turnRobotLeft()
        {
            GameplayScreen.RobotSpriteRef.RenderTransformOrigin = new Point(0.5, 0.5);
                rt.Angle = -90;
                tg.Children.Add(rt);
                GameplayScreen.RobotSpriteRef.RenderTransform = tg;
            turnOccured = true;
        }

        private static void turnRobotRight()
        {
            rt.Angle = 90;
            GameplayScreen.RobotSpriteRef.RenderTransformOrigin = new Point(0.5, 0.5);
            tg.Children.Add(rt);
            GameplayScreen.RobotSpriteRef.RenderTransform = tg;
            turnOccured = true;
        }

        private static void moveRobotStraight(String i) //we've established we're going straight, get parameter, direction.
        {
            if (userHasHitObstacleOrWall == false)
            {
                int index = i.IndexOf('t');
                index = index + 8;
                char integerinquestion = i[index];
                int a = int.Parse(integerinquestion.ToString());
                if (turnOccured == true) // remove transformations so we can use appropriate sprite animation sequence
                {
                    tg.Children.Clear();
                    GameplayScreen.RobotSpriteRef.RenderTransform = tg;
                }

                if (GameplayScreen.RobotCurrentDirection.Equals("North"))
                {
                    MoveStraightNorth.moveRobotStraightNorth(a);
                }
                else if (GameplayScreen.RobotCurrentDirection.Equals("East"))
                {
                    MoveStraightEast.moveRobotStraightEast(a);
                }
                else if (GameplayScreen.RobotCurrentDirection.Equals("West"))
                {
                    MoveStraightWest.moveRobotStraightWest(a);
                }
                else if (GameplayScreen.RobotCurrentDirection.Equals("South"))
                {
                    MoveStraightSouth.moveRobotStraightSouth(a);
                }
            }
         
         

        }

        private async static void useAppropriateDelayFor()
        {
            if(lastCommandInForLoop.Contains("Go Straight 1"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(3500));
            }
            else if (lastCommandInForLoop.Contains("Go Straight 2"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(7000));
            }
            else if (lastCommandInForLoop.Contains("Go Straight 3"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(9000));
            }
            else if (lastCommandInForLoop.Contains("Go Straight 4"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(11000));
            }
        }

        private async static void useAppropriateDelayWhile()
        {
            if (lastCommandInWhileLoop.Contains("Go Straight 1"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(3000));
            }
            else if (lastCommandInWhileLoop.Contains("Go Straight 2"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(5000));
            }
            else if (lastCommandInWhileLoop.Contains("Go Straight 3"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(7000));
            }
            else if (lastCommandInWhileLoop.Contains("Go Straight 4"))
            {
                await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(9000));
            }
        }

       
    }
}
